package net.extrema.td.utils;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import net.extrema.td.db.Database;
import net.extrema.td.utils.feeders.APostsFeeder;
import org.slf4j.Logger;

/**
 * Thread lanciato alla pressione di CTRL+C.
 * @author Libanori Marco
 */
public final class ShutdownHookThread implements Runnable {

    /**
     * Referenza al thread pool.
     */
    private final ExecutorService executor;

    /**
     * Logger.
     */
    private final Logger logger;

    /**
     * Tempo di attesa per la fine dei thread del pool.
     */
    private final int waitTime;

    /**
     * Referenza al feeder su cui invocare lo shutdown.
     */
    private final APostsFeeder feeder;

    /**
     * Referenza al database.
     */
    private final Database database;

    /**
     * Costruttore di default.
     * @param xctr Thread pool
     * @param externalLogger Logger esterno
     * @param externalWaitTime Tempo di attesa
     * @param externalFeeder Feeder su cui invocare lo shutdown
     * @param externalDatabase Riferimento al database
     */
    public ShutdownHookThread(final Logger externalLogger, final ExecutorService xctr, final int externalWaitTime,
            final APostsFeeder externalFeeder, final Database externalDatabase) {
        this.executor = xctr;
        this.logger = externalLogger;
        this.waitTime = externalWaitTime;
        this.feeder = externalFeeder;
        this.database = externalDatabase;
    }

    /**
     * Esegue la logica prima dello shutdown.
     */
    public void run() {
        try {
            feeder.shutdownFeedingThread();
            logger.info("Closing the application...");
            executor.shutdownNow(); // Cancel currently executing tasks
            // Wait a while for tasks to respond to being cancelled
            if (!executor.awaitTermination(waitTime, TimeUnit.MINUTES)) {
                logger.error("Pool did not terminate");
            }
            //
            database.shutdown();
            //
            Configurations.getInstance().storeToFilesystem();
        } catch (InterruptedException ex) {
            logger.error("Shutdown hook interrupted!", ex);
        } catch (IOException ex) {
            logger.error("Shutdown hook interrupted!", ex);
        }
    }
}
